/**  
 * All rights Reserved, Designed By <a href="www.itttq.com" target="_blank">www.itttq.com</a>
 * @date:   2017-07-21 11:42:21
 * @Copyright: 2017 <a href="www.itttq.com" target="_blank">www.itttq.com</a> Inc. All rights reserved. 
 */
package com.itttq.gshop.pbpm.service;

import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.itttq.gshop.domain.po.SysSetPo;
import com.itttq.gshop.domain.po.UserInfoPo;
import com.itttq.gshop.domain.po.UserScorePo;
import com.itttq.gshop.domain.to.IndexStatTo;
import com.itttq.gshop.domain.to.ResultPageTo;
import com.itttq.gshop.generic.util.Constants;
import com.itttq.gshop.generic.util.Constants.ScoreChangeCode;
import com.itttq.gshop.generic.util.EncryptUtil;
import com.itttq.gshop.pbpm.mapper.IUserInfoMapper;
import com.itttq.gshop.pbpm.mapper.IUserScoreMapper;

@Service
public class UserInfoService {
	// 存储所有的推广码，暂时这样放，后续放redis
	public static Map<String, UserInfoPo> promoteCodeMap = null;
	@Autowired
	private IUserInfoMapper userInfoMapper;
	@Autowired
	private IUserScoreMapper userScoreMapper;
	@Autowired
	private SysSetService sysSetService;
	
	@Value("${gshop.pdpm.prop.username.pre}")
	private String usernamePre;
	/**
	 * 根据ID获取UserInfoPo对象
	 * 
	 * @param id
	 * @return
	 * @Author 迷蝶
	 * @return UserInfoPo
	 */
	public UserInfoPo getUserInfo(int id) {
		return userInfoMapper.findUserInfoById(id);
	}
	/**
	 * 根据OpenID获取UserInfoPo对象
	 * 
	 * @param openId
	 * @Author 迷蝶
	 * @return UserInfoPo
	 */
	public UserInfoPo getUserByOpenid(String openid) {
		UserInfoPo userInfo = new UserInfoPo();
		userInfo.setOpenid(openid);
		List<UserInfoPo> users = userInfoMapper.findUserInfos(userInfo);
		return null != users && !users.isEmpty() ? users.get(0) : null;
	}
	
	/**
	 * 根据条件获取UserInfoPo对象，不返回查询的数据总数
	 * 
	 * @param userInfo
	 * @Author 迷蝶
	 * @return ResultPageTo<UserInfoPo>
	 */
	public List<UserInfoPo> getUsers(UserInfoPo userInfo) {
		return userInfoMapper.findUserInfos(userInfo);
	}
	
	/**
	 * 根据条件获取UserInfoPo对象，并返回查询的数据总数
	 * 
	 * @param userInfo
	 * @Author 迷蝶
	 * @return ResultPageTo<UserInfoPo>
	 */
	public ResultPageTo<UserInfoPo> getUserInfos(UserInfoPo userInfo) {
		return new ResultPageTo<UserInfoPo>(userInfo.getStart(), userInfo.getSize(), 
				userInfoMapper.findUserInfoCount(userInfo), userInfoMapper.findUserInfos(userInfo));
	}
	
	/**
	 * 增加用户积分
	 * 
	 * @param score	增加的积分数
	 * @param userId	用户id
	 * @param scc		增加原由
	 * @Author 迷蝶
	 * @return void
	 */
	public void addScore(int score, int userId, ScoreChangeCode scc) {
		scoreChange(score, userId, scc, Constants.SCORE_CHANGE_ADD);
	}
	
	/**
	 * 扣减用户积分，考虑和增加合并为一个方法
	 * 
	 * @param score
	 * @Author 迷蝶
	 * @return ResultPageTo<UserInfoPo>
	 */
	public void deductScore(int score, int userId, ScoreChangeCode scc) {
		scoreChange(score, userId, scc, Constants.SCORE_CHANGE_DEDUCT);
	}
	/**
	 * 积分变化方法
	 * 
	 * @Author 迷蝶
	 * @return void
	 */
	@Transactional
	private void scoreChange(int score, int uid, ScoreChangeCode scc, String change) {
		UserInfoPo user = userInfoMapper.findUserInfoById(uid);
		Integer scoreBefore = user.getMemberScore();
		scoreBefore = null == scoreBefore ? 0 : scoreBefore;
		int scoreAfter = 0;
		if(Constants.SCORE_CHANGE_DEDUCT.equals(change)) {
			scoreAfter = scoreBefore - score;
			// 判断积分是否够扣减
			if(scoreAfter < 0) {
				// TODO GXG 告知积分不足
				return;
			}
		} else {
			scoreAfter = scoreBefore + score;
		}
		
		// 更新积分
		user.setMemberScore(scoreAfter);
		userInfoMapper.updateUserInfo(user);
		// 扣减积分变化日志
		UserScorePo userScore = new UserScorePo();
		userScore.setChange(change);
		userScore.setChangeReasonCode(scc.getText());
		userScore.setChangeReasonDesc(scc.getVal());
		userScore.setScoreAfter(scoreAfter);
		userScore.setScoreBefor(scoreBefore);
		userScore.setScoreChange(score);
		userScore.setUserId(uid);
		userScore.setUserName(user.getUsername());
		userScoreMapper.addUserScore(userScore);
	}
	
	/**
	 * 根据ID删除UserInfoPo对象
	 * 
	 * @param id
	 * @Author 迷蝶
	 */
	public Integer delUserInfo(int id) {
		return userInfoMapper.delUserInfoById(id);
	}
	
	/**
	 * 根据手机号判断用户是否存在
	 * 
	 * @param mobile	手机号
	 * @Author 迷蝶
	 * @return boolean	存在则返回true，反之返回false
	 */
	public boolean exist(String mobile) {
		UserInfoPo user = new UserInfoPo();
		user.setMobile(mobile);
		List<UserInfoPo> users = userInfoMapper.findUserInfos(user);
		return null == users || users.isEmpty() ? false : true;
	}
	
	/**
	 * 增加UserInfoPo对象，密码字段会加密
	 * 
	 * @param userInfo
	 * @Author 迷蝶
	 */
	public Integer reg(UserInfoPo userInfo) {
		UserInfoPo userPromo = null;
		try {
			// 由于微信登录没有设置密码
			if(StringUtils.isNotBlank(userInfo.getPassword())) {
				// 生成盐值和密码
				setPwdAndSlat(userInfo);
			}
			// 生成用户名
			if(StringUtils.isBlank(userInfo.getUsername())) {
				userInfo.setUsername(Constants.getUsername(usernamePre));
			}
			// 判断是否有推广码，有则根据推广码查询用户信息并写入
			if(StringUtils.isNoneBlank(userInfo.getPromoCode())) {
				userPromo = getUserByPromoCode(userInfo.getPromoCode());
				if(null != userPromo) {
					userInfo.setPromoterId(userPromo.getId());
					userInfo.setPromoterName(userPromo.getUsername());
				}
			}
			userInfo.setPromoCode(createPromoteCode());
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		int rs = userInfoMapper.addUserInfo(userInfo);
		// 判断并赠送注册积分，此处异常不影响正常注册
		if(rs > 0) {
			try {
				SysSetPo set = sysSetService.getSysSet(Constants.SCORE_GIVE_MAX);
				int scoreMax = getScoreSet(set);
				set = sysSetService.getSysSet(Constants.SCORE_MEMBER_REG);
				int score = getScoreSet(set);
				// 获取设置的参数值，判断是否赠送
				// 赠送注册积分
				if(score > 0 && score <= scoreMax) {
					addScore(score, userInfo.getId(), ScoreChangeCode.REG);
				}
				// 赠送推广注册积分
				if(null != userPromo) {
					set = sysSetService.getSysSet(Constants.SCORE_MEMBER_REG_PROMOTE);
					score = getScoreSet(set);
					if(score > 0 && score <= scoreMax) {
						addScore(score, userPromo.getId(), ScoreChangeCode.REG_PROMOTE);
					}
				}
			} catch(Exception e) {
				e.printStackTrace();
			}
		}
		return rs;
	}
	private int getScoreSet(SysSetPo set) {
		int rs = 0;
		if(null != set && StringUtils.isNoneBlank(set.getValue()) && Integer.valueOf(set.getValue()) > 0) {
			rs = Integer.valueOf(set.getValue());
		}
		return rs;
	}
	/**
	 * 设置用户盐值和加密后的密码
	 * 
	 * @param userInfo
	 * @throws NoSuchAlgorithmException
	 * @Author 迷蝶
	 * @return void
	 */
	private void setPwdAndSlat(UserInfoPo userInfo) throws NoSuchAlgorithmException {
		// 生成盐值和密码
		String salt = Constants.genRandomChar(6);
		userInfo.setSalt(salt);
		userInfo.setPassword(EncryptUtil.getPassword(userInfo.getPassword(), salt));
	}
	
	/**
	 * 生成不重复的推广码
	 * 
	 * @Author 迷蝶
	 * @return String	生成的推广码
	 */
	private String createPromoteCode() {
		String promoCode = Constants.genRandomCode(6);
		while(getUserByPromoCode(promoCode) == null) {
			break;
		}
		return promoCode;
	}
	/**
	 * 根据推广码查询用户信息
	 * 
	 * @param promoCode
	 * @Author 迷蝶
	 * @return UserInfoPo	用户存在在返回用户对象，不存在则返回null
	 */
	private UserInfoPo getUserByPromoCode(String promoCode) {
		if(null == promoteCodeMap) {
			promoteCodeMap = new HashMap<String, UserInfoPo>();
			List<UserInfoPo> users = userInfoMapper.findAllUsers();
			for(UserInfoPo user : users) {
				if(StringUtils.isNoneBlank(user.getPromoCode())) {
					promoteCodeMap.put(user.getPromoCode(), user);
				}
			}
		}
		
		return promoteCodeMap.get(promoCode);
	}
	
	/**
	 * 使用手机号和密码登录。TODO GXG 记录最后一次登录时间和登录IP
	 * 
	 * @param mobile	手机号
	 * @param password	密码
	 * @param ip		登录IP
	 * @Author 迷蝶
	 * @return SysUserPo	为null表示用户名或密码错误
	 */
	public UserInfoPo login(String mobile, String password, String ip) {
		UserInfoPo user = new UserInfoPo();
		user.setMobile(mobile);
		List<UserInfoPo> users = userInfoMapper.findUserInfos(user);
		if(null == users || users.isEmpty()) {
			user = null;
		} else {
			user = users.get(0);
			try {
				if(!user.getPassword().equals(EncryptUtil.getPassword(password, user.getSalt()))) {
					user = null;
				} else {
					// 更新用户的最后登录时间（时间在更新IP时会自动更新更新时间）和ip
					user.setIpLastLogin(ip);
					userInfoMapper.updateUserInfo(user);
				}
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
				user = null;
			}
		}
		return user;
	}
	
	/**
	 * 根据条件更新UserInfoPo对象
	 * 
	 * @param userInfo
	 * @Author 迷蝶
	 */
	public Integer updateUserInfo(UserInfoPo userInfo) {
		return userInfoMapper.updateUserInfo(userInfo);
	}

	/**
	 * 获取今天新增用户
	 * 
	 * @Author 迷蝶
	 * @return IndexStatTo
	 */
	public IndexStatTo getUserCountToday() {
		return userInfoMapper.findUserCountToday();
	}
	
	/**
	 * 根据手机号更新密码
	 * 
	 * @param userInfoPo
	 * @Author 迷蝶
	 * @return Integer
	 */
	public Integer updatePwdByMobile(UserInfoPo userInfo) {
		try {
			setPwdAndSlat(userInfo);
			return userInfoMapper.updatePwdByMobile(userInfo);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return 0;
	}
}
